import {getDicts} from '@/api/dict'
import {App, Plugin, ref, toRefs} from 'vue'

/**
 *
 * @param component 需要注册的组件
 * @param alias 组件别名
 * @returns any
 */
export const withInstall = <T>(component: T, alias?: string) => {
    const comp = component as any
    comp.install = (app: App) => {
        app.component(comp.name || comp.displayName, component)
        if (alias) {
            app.config.globalProperties[alias] = component
        }
    }
    return component as T & Plugin
}

/**
 * @param str 需要转下划线的驼峰字符串
 * @returns 字符串下划线
 */
export const humpToUnderline = (str: string): string => {
    return str.replace(/([A-Z])/g, '-$1').toLowerCase()
}

/**
 * @param str 需要转驼峰的下划线字符串
 * @returns 字符串驼峰
 */
export const underlineToHump = (str: string): string => {
    return str.replace(/\-(\w)/g, (_, letter: string) => {
        return letter.toUpperCase()
    })
}

export const setCssVar = (prop: string, val: any, dom = document.documentElement) => {
    dom.style.setProperty(prop, val)
}

/**
 * 查找数组对象的某个下标
 * @param {Array} ary 查找的数组
 * @param {Functon} fn 判断的方法
 */
// eslint-disable-next-line
export const findIndex = <T = Recordable>(ary: Array<T>, fn: Fn): number => {
    if (ary.findIndex) {
        return ary.findIndex(fn)
    }
    let index = -1
    ary.some((item: T, i: number, ary: Array<T>) => {
        const ret: T = fn(item, i, ary)
        if (ret) {
            index = i
            return ret
        }
    })
    return index
}

export const trim = (str: string) => {
    return str.replace(/(^\s*)|(\s*$)/g, '')
}

/**
 * @param {Date | number | string} time 需要转换的时间
 * @param {String} fmt 需要转换的格式 如 yyyy-MM-dd、yyyy-MM-dd HH:mm:ss
 */
export function formatTime(time: Date | number | string, fmt: string) {
    if (!time) return ''
    else {
        const date = new Date(time)
        const o = {
            'M+': date.getMonth() + 1,
            'd+': date.getDate(),
            'H+': date.getHours(),
            'm+': date.getMinutes(),
            's+': date.getSeconds(),
            'q+': Math.floor((date.getMonth() + 3) / 3),
            S: date.getMilliseconds()
        }
        if (/(y+)/.test(fmt)) {
            fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
        }
        for (const k in o) {
            if (new RegExp('(' + k + ')').test(fmt)) {
                fmt = fmt.replace(
                    RegExp.$1,
                    RegExp.$1.length === 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length)
                )
            }
        }
        return fmt
    }
}

/**
 * 生成随机字符串
 */
export function toAnyString() {
    const str: string = 'xxxxx-xxxxx-4xxxx-yxxxx-xxxxx'.replace(/[xy]/g, (c: string) => {
        const r: number = (Math.random() * 16) | 0
        const v: number = c === 'x' ? r : (r & 0x3) | 0x8
        return v.toString()
    })
    return str
}

export function getImageUrl(url) {
    return new URL(`/src/assets/imgs/${url}`, import.meta.url).href
}

// 添加日期范围
export function addDateRange(params?: any, dateRange?: string[], propName?: string) {
    const search = params
    search.params =
        typeof search.params === 'object' && search.params !== null && !Array.isArray(search.params)
            ? search.params
            : {}
    dateRange = Array.isArray(dateRange) ? dateRange : []
    if (typeof propName === 'undefined') {
        search.params['beginTime'] = dateRange[0]
        search.params['endTime'] = dateRange[1]
    } else {
        search.params['begin' + propName] = dateRange[0]
        search.params['end' + propName] = dateRange[1]
    }
    return search
}

/**
 * 获取字典状态
 */
export function useDict(...args: string[]) {
    const res = ref({})
    return (() => {
        args.forEach((d) => {
            res.value[d] = []
            getDicts(d).then((resp) => {
                res.value[d] = resp.data.map((p) => ({
                    label: p.dictLabel,
                    value: p.dictValue,
                    elTagType: p.listClass,
                    elTagClass: p.cssClass
                }))
            })
        })
        return toRefs(res.value)
    })()
}

/**
 * 转换字符串，undefined,null等转化为
 * @param str 需要转换的字符串
 */
export function parseStrEmpty(str: any): string {
    if (!str || str == 'undefined' || str == 'null') {
        return ''
    }
    return str
}

// 验证是否为blob格式
export async function blobValidate(data): Promise<boolean> {
    try {
        const text = await data.text()
        JSON.parse(text)
        return false
    } catch (error) {
        return true
    }
}

/**
 * 获取当前时间 yyyy-MM-dd
 */
export function getDay() {
    const nowDate = new Date()
    const year = nowDate.getFullYear()
    const month =
        nowDate.getMonth() + 1 < 10 ? '0' + (nowDate.getMonth() + 1) : nowDate.getMonth() + 1
    const day = nowDate.getDate() < 10 ? '0' + nowDate.getDate() : nowDate.getDate()
    const dateStr = year + '-' + month + '-' + day
    return dateStr
}

/* 通过出生日期获取当前年龄
 * @param strBirthday：指的是出生日期，格式为"1990-01-01",字符串类型
 */
export function getCurrentAgeByBirthDate(strBirthday) {
    // 将出生日期的字符串通过"-"分割成数组
    const strBirthdayArr = strBirthday.split('-')
    // 拿到出生日期的年
    const birthYear = strBirthdayArr[0]
    // 拿到出生日期的月
    const birthMonth = strBirthdayArr[1]
    // 拿到出生日期的日
    const birthDay = strBirthdayArr[2]
    // 创建一个时间对象
    const d = new Date()
    // 拿到当前时间的年
    const nowYear = d.getFullYear()
    // 拿到当前时间的月
    const nowMonth = d.getMonth() + 1
    // 拿到当前时间的日
    const nowDay = d.getDate()
    // 如果出生日期的年等于当前时间的年
    if (nowYear === birthYear) return 0 // 返回周岁年龄 0,并终止函数执行
    // 如果如果出生日期的年不等于于当前时间的年,则拿到年之差
    const ageDiff = nowYear - birthYear // 年之差
    // 如果年之差是个负数,则表示用户输入的出生日期错误,晚于今天,返回 -1,并终止函数执行
    if (ageDiff < 0) return -1 // 返回错误 -1,并终止函数执行
    // 如果年之差是个正整数,但出生日期的月与当前时间的月不相等
    if (nowMonth !== birthMonth) {
        // 拿到出生日期的日与当前时间的月之差
        const monthDiff = nowMonth - birthMonth // 月之差
        // 如果月之差是个负数,则年之差 - 1后得到周岁年龄,否则直接得到周岁年龄
        return monthDiff < 0 ? ageDiff - 1 : ageDiff // 返回周岁年龄,并终止函数执行
    }
    // 如果出生日期的月与当前时间的月相等,则拿到出生日期的日与当前时间的日之差
    const dayDiff = nowDay - birthDay
    // 如果日之差是个负数,则年之差 - 1得到周岁年龄,否则直接得到周岁年龄
    return dayDiff < 0 ? ageDiff - 1 : ageDiff // 返回周岁年龄,并终止函数执行
}
